/**
 *******************************************************************************
 * @file analog_monitor.c
 * @author .ISS_AUTO (hudandan@issauto.com)
 * @note 2025-05-09  1. 应用于 AK601
 *                      - ADC1: 1. 遥感x2
 *                      - ADC3: 1. VBAT
 *
 * @brief This file is for the analog monitor module.
 *
 * @copyright Copyright (c) 2024 ISSAUTO TECH Co., Ltd. All rights reserved.
 *
 *******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "analog_monitor.h"

/* Exported Function ---------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
typedef struct {
    float OP_UP_LIMIT;  //!< 原点限幅上限位
    float OP_DN_LIMIT;  //!< 原点限幅下限位

    float VOLT_RANGE_MAX;   //!< 最大值
    float VOLT_RANGE_MIN;   //!< 最小值

    /* Normalization */
    uint32_t RANGE_MAX;   //!< 量程最大值
    uint32_t RANGE_MID;   //!< 量程中间值
    uint32_t RANGE_MIN;   //!< 量程最小值

} stick_control_type_t; //!< 摇杆电位器

stick_control_type_t stickFunc[ADC1_CHAN_NUM] = {0};

/* Private define ------------------------------------------------------------*/
#define adc_log(M, ...)    USER_PRINTF("[ADC] "M"\r\n", ##__VA_ARGS__)
// #define adc_log(M, ...)

#define ADC_STATIC        static
// #define ADC_STATIC

/* Private macro -------------------------------------------------------------*/
/* ADC 参考电压 */
#define ADC_REF_VOLT                   (3.3f)

/* ADC1 Buffer长度 */
#define ADC1_SampleShiftNum            (4U)
#define ADC1_SAMPLE_SIZE               (1U << ADC1_SampleShiftNum) //!< ADC1 total Sample number

/*!< User Application Definitions ... */

/* 电位器滤波检测 */
#define POT_1_ORIGIN_POINT_VALUE     (1.65f) //!< 电位器1 原点处电压值
#define POT_2_ORIGIN_POINT_VALUE     (1.65f) //!< 电位器2 原点处电压值

#define POT_OP_GLITCH_FILTER_VALUE   (0.08f) //!< 电位器原点处消抖值
#define POT_RANGE_VALUE_HALF         (1.1f) //!< 电位器量程的一半 (最大值 - 最小值 ~= 2.2f)

/* 摇杆量程设定 */
#define REMOTE_VERTICAL_RANGE_MAX      (100)
#define REMOTE_VERTICAL_RANGE_MID      (50) //!< (REMOTE_VERTICAL_RANGE_MAX / 2)
#define REMOTE_VERTICAL_RANGE_MIN      (0)

#define REMOTE_HORIZONTAL_RANGE_MAX    (100)
#define REMOTE_HORIZONTAL_RANGE_MID    (50) //!< (REMOTE_HORIZONTAL_RANGE_MAX / 2)
#define REMOTE_HORIZONTAL_RANGE_MIN    (0)



/* ADC3 Buffer长度 */
#define ADC3_SampleShiftNum            (4U)
#define ADC3_SAMPLE_SIZE               (1 << ADC3_SampleShiftNum) //!< ADC3 total Sample number

/*!< User Application Definitions ... */
/* Battery采样分压电阻 */
/* 10K/(100K+10K) */
#define BATTERY_RES1                   (100.0f)
#define BATTERY_RES2                   (10.0f)

/* Safety Monitor */
#define SW_OVER_VOLT                   (1U << 0)
#define SW_UNDER_VOLT                  (1U << 1)

/* User Application Threshold */
#define BATT_UNDER_VOLT_ADC            (1200) // 实际约 6.0V
#define BATT_OVER_VOLT_ADC             (3500) // 实际约 17.0V
#define BATT_RELEASE_VOLT_ADC_RANGE    (60)

#define BATT_UNDER_VOLT_LEVEL          (9.0f)  // V
#define BATT_OVER_VOLT_LEVEL           (16.0f) // V
#define BATT_RELEASE_VOLT_RANGE        (0.2f)


/* Exported variables --------------------------------------------------------*/
ADC_STATIC analog_paramInfo_t monitorParam = {0};

/* Private variables ---------------------------------------------------------*/
ADC_STATIC __IO uint8_t ADC1_ConvCplt_Flag = 0;
ADC_STATIC __IO uint16_t ADC1_FilterValue[ADC1_CHAN_NUM] = {0};
ADC_STATIC __IO uint16_t ADC1ConversionValueBuffer[ADC1_SAMPLE_SIZE + 1/*防止溢出*/][ADC1_CHAN_NUM] = {0};

ADC_STATIC __IO uint8_t ADC3_ConvCplt_Flag = 0;
ADC_STATIC __IO uint16_t ADC3_FilterValue[ADC3_CHAN_NUM] = {0};
ADC_STATIC __IO uint16_t ADC3ConversionValueBuffer[ADC3_SAMPLE_SIZE + 1/*防止溢出*/][ADC3_CHAN_NUM] = {0};

/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/* PRQA S 3384 ++ */


/*******************************************************************************
 *                             Analog Monitor Task
********************************************************************************/

/**
 * @brief 获取指向模拟信号监控模块相关参数信息的指针地址
 *
 * @return monitorParam*
 */
analog_paramInfo_t *Get_Analog_Monitor_Info(void)
{
    return &monitorParam;
}

#if (0)
/**
 * @brief BatteryVolt Diagnostics
 *
 * @return void
 */
void Analog_BattVoltDiagnostics(void)
{
    static uint16_t VCC_CampCnt[2] = {0};
    int BattMin_Sta;
    int BattMax_Sta;
    float VCC_Volt;

    VCC_Volt = (float)((ADC2_FilterValue[ADC2_CHAN_VBAT]) * ADC_REF_VOLT / 4095) * (BATTERY_RES1 + BATTERY_RES2) / BATTERY_RES2 + 1.0f;

    // VCC_Volt = (float)ADC2_FilterValue[ADC2_CHAN_VBAT]; // ADC

    BattMin_Sta = Amplitude_Limiter_Compare(&VCC_CampCnt[0], VCC_Volt, BATT_UNDER_VOLT_LEVEL, BATT_RELEASE_VOLT_RANGE, 10/*FILTER_TIME*/);
    BattMax_Sta = Amplitude_Limiter_Compare(&VCC_CampCnt[1], VCC_Volt, BATT_OVER_VOLT_LEVEL, BATT_RELEASE_VOLT_RANGE,  10/*FILTER_TIME*/);

    if (monitorParam.safetyState & (SW_OVER_VOLT | SW_UNDER_VOLT))  {
        /* Over VoltMin & under VoltMax */
        if ((BattMax_Sta == COMPARE_RESULT_UNDER) && (BattMin_Sta == COMPARE_RESULT_OVER)) {
            monitorParam.safetyState &= ~(SW_OVER_VOLT | SW_UNDER_VOLT);
        }

    } else {
        /* Over volt ---------------------*/
        if (BattMax_Sta == COMPARE_RESULT_OVER) {
            monitorParam.safetyState |= SW_OVER_VOLT;
        }

        /* Under volt --------------------*/
        if (BattMin_Sta == COMPARE_RESULT_UNDER) {
            monitorParam.safetyState |= SW_UNDER_VOLT;
        }
    }

    monitorParam.Battery_Volt = VCC_Volt;
}
#endif

/*******************************************************************************
 *                             Analog Monitor Task
********************************************************************************/

/**
 * @brief 模拟信号监控模块的采集完成回调函数
 *
 * @param[in] arg 指向外设配置相关用户参数
 * @return none
 */
void ADC1_ConvCpltCallback(void *arg)
{
    uint32_t SumVal;
    size_t chan, i;

    (void)arg;

    #if (ADC1_CHAN_NUM > 1)

    for (chan = 0; chan < ADC1_CHAN_NUM; chan++) {
    #else

    chan = 0;
    #endif

        SumVal = 0;

        for (i = 0; i < ADC1_SAMPLE_SIZE; i++) {
            if (ADC1ConversionValueBuffer[i][chan] > 4095) {
                break;
            }

            SumVal += ADC1ConversionValueBuffer[i][chan];
        }

        if (i == ADC1_SAMPLE_SIZE) {
            /* AD数值简单均值滤波处理 */
            ADC1_FilterValue[chan] = SumVal >> ADC1_SampleShiftNum;
        }

        #if (ADC1_CHAN_NUM > 1)
    }

        #endif

    ADC1_ConvCplt_Flag = 1;
}

/**
 * @brief 模拟信号监控模块的采集完成回调函数
 *
 * @param[in] arg 指向外设配置相关用户参数
 * @return none
 */
void ADC3_ConvCpltCallback(void *arg)
{
    uint32_t SumVal;
    size_t chan, i;

    (void)arg;

    #if (ADC3_CHAN_NUM > 1)

    for (chan = 0; chan < ADC3_CHAN_NUM; chan++) {
    #else

    chan = 0;
    #endif

        SumVal = 0;

        for (i = 0; i < ADC3_SAMPLE_SIZE; i++) {
            if (ADC3ConversionValueBuffer[i][chan] > 4095) {
                break;
            }

            SumVal += ADC3ConversionValueBuffer[i][chan];
        }

        if (i == ADC3_SAMPLE_SIZE) {
            /* AD数值简单均值滤波处理 */
            ADC3_FilterValue[chan] = SumVal >> ADC3_SampleShiftNum;
        }

        #if (ADC3_CHAN_NUM > 1)
    }

        #endif

    ADC3_ConvCplt_Flag = 1;
}

/**
 * @brief Low Power Configuration.
 *
 * @param[in] void
 * @return void
 */
void Analog_Monitor_DeInit(void)
{
    ADC1_LP_Configuration();

    for (size_t i = 0; i < ADC1_CHAN_NUM; i++) {
        adc_log("@ ADC[%d]: %.3fV", i, monitorParam.Cur_Volt1[i]);
    }

    ADC3_LP_Configuration();

    for (size_t i = 0; i < ADC3_CHAN_NUM; i++) {
        adc_log("@ ADC[%d]: %.3fV", i, monitorParam.Cur_Volt3[i]);
    }

}

/**
 * @brief Analog Monitor Application Driver layer initialization.
 *
 * @param[in] void
 * @return void
 */
void Analog_Monitor_Init(void)
{
    /* Initializes ADC1 Driver --------------------------------*/
    ADC_DMA_DriverTypeDef dadc1_dma = {0};

    dadc1_dma.DMA_InitParam.PeriphAddr     = (uint32_t)&ADC1->DAT;
    dadc1_dma.DMA_InitParam.MemAddr        = (uint32_t)ADC1ConversionValueBuffer;
    dadc1_dma.DMA_InitParam.Direction      = DMA_DIR_PERIPH_SRC;
    dadc1_dma.DMA_InitParam.BufSize        = ADC1_SAMPLE_SIZE * ADC1_CHAN_NUM;
    dadc1_dma.DMA_InitParam.PeriphInc      = DMA_PERIPH_INC_DISABLE;
    dadc1_dma.DMA_InitParam.DMA_MemoryInc  = DMA_MEM_INC_ENABLE;
    dadc1_dma.DMA_InitParam.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
    dadc1_dma.DMA_InitParam.MemDataSize    = DMA_MemoryDataSize_HalfWord;
    dadc1_dma.DMA_InitParam.CircularMode   = DMA_MODE_CIRCULAR;
    dadc1_dma.DMA_InitParam.Priority       = DMA_PRIORITY_HIGH;
    dadc1_dma.DMA_InitParam.Mem2Mem        = DMA_M2M_DISABLE;

    dadc1_dma.DMA_RxCpltCallback           = ADC1_ConvCpltCallback;

    /* ADC1 configuration */
    ADC1_Configuration((void *)&dadc1_dma);

    ADC1_ConvCplt_Flag = 0;


    /* Initializes ADC3 Driver --------------------------------*/
    ADC_DMA_DriverTypeDef dadc3_dma = {0};

    dadc3_dma.DMA_InitParam.PeriphAddr     = (uint32_t)&ADC3->DAT;
    dadc3_dma.DMA_InitParam.MemAddr        = (uint32_t)ADC3ConversionValueBuffer;
    dadc3_dma.DMA_InitParam.Direction      = DMA_DIR_PERIPH_SRC;
    dadc3_dma.DMA_InitParam.BufSize        = ADC3_SAMPLE_SIZE * ADC3_CHAN_NUM;
    dadc3_dma.DMA_InitParam.PeriphInc      = DMA_PERIPH_INC_DISABLE;
    dadc3_dma.DMA_InitParam.DMA_MemoryInc  = DMA_MEM_INC_ENABLE;
    dadc3_dma.DMA_InitParam.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
    dadc3_dma.DMA_InitParam.MemDataSize    = DMA_MemoryDataSize_HalfWord;
    dadc3_dma.DMA_InitParam.CircularMode   = DMA_MODE_CIRCULAR;
    dadc3_dma.DMA_InitParam.Priority       = DMA_PRIORITY_HIGH;
    dadc3_dma.DMA_InitParam.Mem2Mem        = DMA_M2M_DISABLE;

    dadc3_dma.DMA_RxCpltCallback           = ADC3_ConvCpltCallback;

    /* ADC3 configuration */
    ADC3_Configuration((void *)&dadc3_dma);

    #if (0)
    /* 上电供电状态诊断 START ↓↓↓ ------------------------------------*/
    ADC3_FilterValue[ADC3_CHAN_VBAT] = 0xFFFF;
    ADC3_ConvCplt_Flag = 0;

    while ((!ADC3_ConvCplt_Flag) || (ADC3_FilterValue[ADC3_CHAN_VBAT] == 0)) {
        ;
    }

    /* 电池电压极限处理 */
    if (ADC3_FilterValue[ADC3_CHAN_VBAT] < (BATT_UNDER_VOLT_ADC + BATT_RELEASE_VOLT_ADC_RANGE)) {
        return (int)DRV_ERROR;
    }

    /* 上电供电状态诊断 END ↑↑↑   ------------------------------------*/
    #endif

    ADC3_ConvCplt_Flag = 0;


    /* Initializes Parameter */
    memset((void *)&monitorParam, 0, sizeof(monitorParam));

    memset(stickFunc, 0, sizeof(stickFunc));

    stickFunc[ADC1_CHAN_V0].OP_UP_LIMIT = POT_1_ORIGIN_POINT_VALUE + POT_OP_GLITCH_FILTER_VALUE;
    stickFunc[ADC1_CHAN_V0].OP_DN_LIMIT = POT_1_ORIGIN_POINT_VALUE - POT_OP_GLITCH_FILTER_VALUE;

    stickFunc[ADC1_CHAN_V0].VOLT_RANGE_MAX = POT_1_ORIGIN_POINT_VALUE + POT_RANGE_VALUE_HALF;
    stickFunc[ADC1_CHAN_V0].VOLT_RANGE_MIN = POT_1_ORIGIN_POINT_VALUE - POT_RANGE_VALUE_HALF;

    stickFunc[ADC1_CHAN_V0].RANGE_MAX = REMOTE_VERTICAL_RANGE_MAX;
    stickFunc[ADC1_CHAN_V0].RANGE_MID = REMOTE_VERTICAL_RANGE_MID;
    stickFunc[ADC1_CHAN_V0].RANGE_MIN = REMOTE_VERTICAL_RANGE_MIN;

    stickFunc[ADC1_CHAN_V1].OP_UP_LIMIT = POT_2_ORIGIN_POINT_VALUE + POT_OP_GLITCH_FILTER_VALUE;
    stickFunc[ADC1_CHAN_V1].OP_DN_LIMIT = POT_2_ORIGIN_POINT_VALUE - POT_OP_GLITCH_FILTER_VALUE;

    stickFunc[ADC1_CHAN_V1].VOLT_RANGE_MAX = POT_2_ORIGIN_POINT_VALUE + POT_RANGE_VALUE_HALF;
    stickFunc[ADC1_CHAN_V1].VOLT_RANGE_MIN = POT_2_ORIGIN_POINT_VALUE - POT_RANGE_VALUE_HALF;

    stickFunc[ADC1_CHAN_V1].RANGE_MAX = REMOTE_HORIZONTAL_RANGE_MAX;
    stickFunc[ADC1_CHAN_V1].RANGE_MID = REMOTE_HORIZONTAL_RANGE_MID;
    stickFunc[ADC1_CHAN_V1].RANGE_MIN = REMOTE_HORIZONTAL_RANGE_MIN;

}

#define DIFFERENT_CNT_MAX         (2)

/**
 * @brief Handle function for Analog Monitor Application Driver layer
 *
 * @param[in] void
 * @return void
 */
void Analog_Monitor_Handle(void)
{
    static uint32_t Point_Diff_Cnt[ADC1_CHAN_NUM] = {0};

    if (ADC1_ConvCplt_Flag) {
        ADC1_ConvCplt_Flag = 0;

        float tempVolt[ADC1_CHAN_NUM];
        uint32_t tempValue_Old[ADC1_CHAN_NUM] = {0};
        uint32_t tempValue_New[ADC1_CHAN_NUM] = {0};

        for (size_t i = 0; i < ADC1_CHAN_NUM; i++) {
            tempVolt[i] = (float)((ADC1_FilterValue[i]) * ADC_REF_VOLT / 4095);

            monitorParam.Cur_Volt1[i] = tempVolt[i];

            tempValue_Old[i] = monitorParam.Stick_Value[i];

            if (tempVolt[i] > stickFunc[i].OP_UP_LIMIT) {
                if (tempVolt[i] < stickFunc[i].VOLT_RANGE_MAX) {
                    tempValue_New[i] = stickFunc[i].RANGE_MID + (tempVolt[i] - stickFunc[i].OP_UP_LIMIT) * stickFunc[i].RANGE_MID / (stickFunc[i].VOLT_RANGE_MAX - stickFunc[i].OP_UP_LIMIT);
                } else {
                    tempValue_New[i] = stickFunc[i].RANGE_MAX;
                }

            } else if (tempVolt[i] < stickFunc[i].OP_DN_LIMIT) {
                if (tempVolt[i] > stickFunc[i].VOLT_RANGE_MIN) {
                    tempValue_New[i] = stickFunc[i].RANGE_MID - (stickFunc[i].OP_DN_LIMIT - tempVolt[i]) * stickFunc[i].RANGE_MID / (stickFunc[i].OP_DN_LIMIT - stickFunc[i].VOLT_RANGE_MIN);
                } else {
                    tempValue_New[i] = stickFunc[i].RANGE_MIN;
                }

            } else {
                tempValue_New[i] = stickFunc[i].RANGE_MID;
            }

            if (tempValue_New[i] != tempValue_Old[i]) {

                Point_Diff_Cnt[i]++;

                if (Point_Diff_Cnt[i] > DIFFERENT_CNT_MAX) {
                    Point_Diff_Cnt[i] = 0;
                    tempValue_Old[i] = tempValue_New[i];
                }
            } else {
                Point_Diff_Cnt[i] = 0;
            }

            monitorParam.Stick_Value[i] = tempValue_New[i];
        }

    }

    if (ADC3_ConvCplt_Flag) {
        ADC3_ConvCplt_Flag = 0;

        float tempVolt[ADC3_CHAN_NUM];

        for (size_t i = 0; i < ADC3_CHAN_NUM; i++) {
            tempVolt[i] = (float)((ADC3_FilterValue[i]) * ADC_REF_VOLT / 4095);

            monitorParam.Cur_Volt3[i] = tempVolt[i];
        }

        monitorParam.Battery_Volt = tempVolt[ADC3_CHAN_VBAT] * (BATTERY_RES1 + BATTERY_RES2) / BATTERY_RES2;

        #if (0)

        /* 电池电压极限处理 -----------------------------------*/
        if (ADC3_FilterValue[ADC3_CHAN_VBAT] < (BATT_UNDER_VOLT_ADC - BATT_RELEASE_VOLT_ADC_RANGE)) {
            // DRV_Status = DRV_ERROR;
        }

        Analog_BattVoltDiagnostics();

        if (monitorParam.safetyState & (SW_OVER_VOLT | SW_UNDER_VOLT))  {
            /* Over VoltMin & under VoltMax: TBD... */


        } else {
            /* Over volt || Under volt: TBD... */

        }

        #endif
    }

}

/* PRQA S 3384 -- */
/* END OF FILE ---------------------------------------------------------------*/
